/**
 * 
 */
package com.estock.web.dao.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.estock.common.consts.DaoQueryConsts;
import com.estock.common.dao.impl.BaseDaoImpl;
import com.estock.common.model.security.Stock;
import com.estock.common.model.security.StockCategory;
import com.estock.common.util.StringUtil;
import com.estock.common.util.support.ESLogger;
import com.estock.web.dao.StockCategoryDao;
import com.estock.web.dao.StockDao;

/**
 * @author richard
 *
 */
@Repository
public class StockDaoImpl extends BaseDaoImpl<Stock> implements StockDao {
	
	private static final ESLogger logger = ESLogger.getLogger(StockDaoImpl.class);
	
	@Resource
	private StockCategoryDao stockCategoryDao;
	
	public StockCategoryDao getStockCategoryDao() {
		return stockCategoryDao;
	}

	@Override
	public Stock findStockByCode(String code) {
		logger.info("Start find stock by code %s", code);
		Criteria criteria = getSession().createCriteria(Stock.class);
		criteria.add(Restrictions.eq(DaoQueryConsts.STOCK_CODE, code));
		
		List<Stock> results = findByCriteria(criteria);
        if (StringUtil.isEmpty(results)) return null;
        return results.get(0);
	}

	@Override
	public List<Stock> findAllStocksByType(int type, int currentPage, int itemsPerPage) {
		logger.info("Start find stocks by type %d, currentPage %d itemsPerPage %d", type, currentPage, itemsPerPage);
		Criteria criteria = getSession().createCriteria(Stock.class);
		criteria.add(Restrictions.eq(DaoQueryConsts.STOCK_TYPE, type));
		criteria.setFirstResult((currentPage - 1) * itemsPerPage);
		criteria.setMaxResults(itemsPerPage);
		criteria.addOrder(Order.asc(DaoQueryConsts.STOCK_CODE));
		List<Stock> results = findByCriteria(criteria);
		
        if (results == null || results.isEmpty()) return new ArrayList<Stock>();
        return results;
	}
	
	@SuppressWarnings("rawtypes")
	@Override
	public int getStockNumByType(int type) throws Exception {
        Map<String, Object> queryParams = new HashMap<String, Object>();
		queryParams.put(DaoQueryConsts.STOCK_TYPE, type);
		List results = findByNamedQuery(DaoQueryConsts.getStockNumByType, queryParams);
		
        if (results == null || results.isEmpty()) return 0;
        return Integer.valueOf(String.valueOf(results.get(0)));
    }     

	@Override
	public List<Stock> findAllStocks() {
		logger.info("Start find all stocks");
		return findAll(getEntityClass(), DaoQueryConsts.STOCK_CODE, true);
	}

	@Override
	public List<Stock> findStocksByCategoryId(int stockCategoryId) {
		logger.info("Start find stocks by category id %d", stockCategoryId);

		StockCategory stockCategory = getStockCategoryDao().findById(Long.valueOf(stockCategoryId));
		List<Stock> stocks = stockCategory.getStocks();
		if (stocks == null) return new ArrayList<Stock>();
		
		// fix LazyInitializationException error
//		for (Stock s: stocks) {
//			s.getName();
//		}
		logger.info("get stocks for categoryid %d with size of %d", stockCategoryId, stocks.size());
		return stocks;
	}
	
	
	//////// Self-Select stock related

	@Override
	@SuppressWarnings("rawtypes")
	public int getSelfSelectNum() throws Exception {
		Map<String, Object> queryParams = new HashMap<String, Object>();
		List results = findByNamedQuery(DaoQueryConsts.getSelfSelectNum, queryParams);
		
        if (results == null || results.isEmpty()) return 0;
        return Integer.valueOf(String.valueOf(results.get(0)));
	}

	@Override
	public List<Stock> findAllSelfSelects(int currentPage, int itemsPerPage) {
		logger.info("Start find self-selct stocks by currentPage %d itemsPerPage %d", currentPage, itemsPerPage);
		Criteria criteria = getSession().createCriteria(Stock.class);
		criteria.setFirstResult((currentPage - 1) * itemsPerPage);
		criteria.setMaxResults(itemsPerPage);
		criteria.add(Restrictions.eq(DaoQueryConsts.STOCK_ISSELFSELCT, 1));
		criteria.addOrder(Order.asc(DaoQueryConsts.STOCK_CODE));
		List<Stock> results = findByCriteria(criteria);
		
        if (results == null || results.isEmpty()) return new ArrayList<Stock>();
        return results;
	}

	@Override
	public Stock findSelfSelectByCode(String code) {
		logger.info("Start find selfSelect by code %s", code);
		Criteria criteria = getSession().createCriteria(Stock.class);
		criteria.add(Restrictions.eq(DaoQueryConsts.STOCK_CODE, code));
		criteria.add(Restrictions.eq(DaoQueryConsts.STOCK_ISSELFSELCT, 1));
		List<Stock> results = findByCriteria(criteria);
		
        if (results == null || results.isEmpty()) return null;
        return results.get(0);
	}

	@Override
	public void updateLatestPrice(String code, float latestPrice) {
		Stock selfSelect = findSelfSelectByCode(code);
		if (selfSelect != null) {
			selfSelect.setLatestPrice(latestPrice);
			saveOrUpdate(selfSelect);
		}
	}

	@Override
	public void deleteSelfSelectById(Long id) {
		Stock stock = findById(id);
		if (stock != null) {
			stock.setIsSelfSelect(false);
		}
		saveOrUpdate(stock);
	}

}
